﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Common.Extensions;
using Common.UI.Controls.Utils;
using Windows.UI.Xaml.Shapes;
using Windows.UI;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace Common.UI.Controls
{
	public sealed partial class LineChart : UserControl
	{
		public LineChart()
		{
			this.InitializeComponent();
		}

		public DoubleSource ValuesSource
		{
			get { return (DoubleSource)GetValue(ValuesSourceProperty); }
			set { SetValue(ValuesSourceProperty, value); }
		}

		public static readonly DependencyProperty ValuesSourceProperty =
			DependencyProperty.Register("ValuesSource", typeof(DoubleSource), typeof(LineChart), new PropertyMetadata(null, OnValuesSourceChanged));


		private static void OnValuesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			(d as LineChart).UpdateChart();
		}

		private void UpdateChart()
		{
			UpdateChart(ActualWidth, ActualHeight);
		}

		private void UpdateChart(double canvasWidth, double canvasHeight)
		{
			if (ValuesSource == null || ValuesSource.Items.IsNullOrEmpty() || (canvasHeight == 0.0 && canvasWidth == 0.0))
				return;

			var points = Convert(ValuesSource.Items, canvasWidth, canvasHeight).ToList();
			aPolygon.Points = ToPointCollection(points, true, canvasWidth, canvasHeight);
			aPolyline.Points = ToPointCollection(points);

			DrawPoints(points, canvasWidth);
		}

		private void DrawPoints(List<Point> points, double canvasWidth)
		{
			Canva.Children.Clear();
			var w = Math.Min(canvasWidth / points.Count * 0.15, 10.0);
			if (w < 4.0)
				return;
			
			foreach (var p in points)
			{
				var el = new Ellipse() { Width = w, Height = w, Fill = new SolidColorBrush(Colors.White) };
				Canvas.SetLeft(el, p.X - w / 2.0);
				Canvas.SetTop(el, p.Y - w / 2.0);
				//el.PointerEntered += el_PointerEntered;
				//el.PointerExited += el_PointerExited;
				Canva.Children.Add(el);
			}
		}

		void el_PointerExited(object sender, PointerRoutedEventArgs e)
		{
			ChangeSize(sender as Ellipse, 30, false);
		}

		void el_PointerEntered(object sender, PointerRoutedEventArgs e)
		{
			ChangeSize(sender as Ellipse, 30, true);
		}

		private static void ChangeSize(Ellipse el, double d, Boolean increase)
		{
			if (increase)
			{
				el.Width += d;
				el.Height += d;
				Canvas.SetLeft(el, Canvas.GetLeft(el) - d / 2.0);
				Canvas.SetTop(el, Canvas.GetTop(el) - d / 2.0);
			}
			else
			{
				el.Width -= d;
				el.Height -= d;
				Canvas.SetLeft(el, Canvas.GetLeft(el) + d / 2.0);
				Canvas.SetTop(el, Canvas.GetTop(el) + d / 2.0);
			}
		}

		private IEnumerable<Point> Convert(IEnumerable<Double> values, double canvasWidth, double canvasHeight)
		{
			var dx = canvasWidth / (values.Count() > 1 ? ((Double)values.Count() - 1) : 1.0);
			var maxValue = values.Max();

			return values.Select((value, i) =>
			{
				var y = canvasHeight - canvasHeight * (value / maxValue);
				return new Point(dx * i, y);
			});
		}

		private PointCollection ToPointCollection(IEnumerable<Point> points, Boolean addB = false, double canvasWidth = 0, double canvasHeight = 0)
		{
			var res = new PointCollection();
			if (addB)
			{
				res.Add(new Point(points.First().X, canvasHeight));
			}
			foreach (var p in points)
			{
				res.Add(p);
			}
			if (addB)
			{
				res.Add(new Point(points.Last().X, canvasHeight));
			}
			return res;
		}

		private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
		{
			UpdateChart(e.NewSize.Width, e.NewSize.Height);
		}
	}
}
